<template>
	<view class="xzy-bigbox">
		<!-- 搜索 -->
		<view class="xzy-search" v-if="isSearch">
			<uv-search placeholder="请输入检索内容" v-model="inputKey" :showAction="false" @search="searchInput"
				@clear="searchInput"></uv-search>
		</view>
		<!-- 搜索内容 -->
		<view v-if="isSearch && searchList.length > 0" class="xzy-searchScroll">
			<scroll-view scroll-y style="width:100%;height:100%;" enable-flex>
				<view>
					<view class="xzy-secondEach" v-for="(item,index) in searchList" :key="item[idValue]" @tap="selectIndex(item)">
						<view class="xzy-avatar" v-if="isAvatar">
							<image :src="replaceUrl(item[avatarValue])" class="xzy-avatarImg"></image>
						</view>
						<view class="xzy-text">
							<view class="xzy-name">{{item[nameValue]}}</view>
							<view class="xzy-fu" v-if="isFu">{{item[fuValue]}}</view>
						</view>
					</view>
				</view>
			</scroll-view>
		</view>

		<!-- 右侧索引 -->
		<view class="xzy-letters" v-if="isLetters&&searchList.length <= 0"
			:style="{'top':isSearch?'90rpx':'0rpx','height':isSearch?'calc(100% - 90rpx)':'100%'}">
			<image @touchmove="handleTouchMove" src="@/static/send/top.png" class="xzy-letterTop" v-if="isTop" @tap="goTop">
			</image>
			<view v-for="(item,index) in letters" :key="item"
				:style="{'height':indexEachHH+'rpx','background-color':(currentCeiling==index&&isIndexAc)?indexAcColor:''}"
				class="xzy-lettersEach" :class="(currentCeiling==index&&isIndexAc)?'xzy-lettersEachAc':''"
				@touchmove="handleTouchMove" @touchend="handleTouchEnd(item,index)" @tap="handleLetterClick(item,index)">
				{{item}}
			</view>
		</view>

		<!-- 提示当前索引 -->
		<view class="xzy-toastIndex" :style="`top: calc(${top}px - 32rpx)`" v-if="isIndexToast && toastIndex">
			<view style="position: absolute;z-index: 1;width: 100%;margin-left: 32rpx;">{{toastIndex}}</view>
			<image src="@/static/send/bg_arrow_zimu.png" mode="aspectFit"
				style="height: 100%;width: 100%;position: absolute;left: 0;"></image>
		</view>

		<!-- 吸顶 -->
		<view class="ceiling" v-if="currentCeiling !== null&&isCeil&&listInfo.length>0&&searchList.length <= 0&&isOkCurrent"
			:style="{'top':isSearch?'90rpx':'0rpx'}">{{listInfo[currentCeiling]?.id.split('-')[1]}}</view>

		<!-- 列表 -->
		<scroll-view scroll-y class="xzy-scroll" @scroll="listenScroll" :scroll-top="scrollTop"
			:scroll-into-view="scrollEachId" v-show="searchList.length <= 0"
			:style="{'top':isSearch?'90rpx':'0rpx','height':isSearch?'calc(100% - 90rpx)':'100%'}">
			<view>
				<view class="xzy-modu" v-if="isCurrentCity || isHotCity">
					<view class="xzy-current" v-if="isCurrentCity">
						<view class="xzy-moduTitle">当前城市</view>
						<view class="xzy-currentBox">
							<view class="xzy-currentLs">
								<image src="@/static/send/posi.png" class="xzy-currentImg"></image>
								<view class="xzy-currentCity" @tap="selectIndex(currentCity)">
									{{currentCity[nameValue] || '暂无'}}
								</view>
							</view>
						</view>
					</view>
					<view class="xzy-hotCity" v-if="isHotCity && hotCity.length>0">
						<view class="xzy-moduTitle">{{hotCityName}}</view>
						<view class="xzy-hotCityBox">
							<view v-for="(item,index) in hotCity" :key="item[idValue]" @tap="selectIndex(item)"
								class="xzy-hotEachCity">{{item[nameValue]}}</view>
						</view>
					</view>
				</view>

				<block v-if="type === 'list'">
					<view v-for="(item,index) in cityList" :key="index" class="xzy-each">
						<view class="xzy-eachTitle" :id="'xzy-'+index">{{index}}</view>
						<view class="xzy-second">
							<view v-for="(ite,ind) in item" :key="ite[idValue]" class="xzy-secondEach" @tap="selectIndex(ite)">
								<view class="xzy-avatar" v-if="isAvatar">
									<image :src="replaceUrl(ite[avatarValue])" class="xzy-avatarImg"></image>
								</view>
								<view class="xzy-text">
									<view class="xzy-name">{{ite[nameValue]}}</view>
									<view class="xzy-fu" v-if="isFu">{{ite[fuValue]}}</view>
								</view>
							</view>
						</view>
					</view>
				</block>
				<block v-else>
					<view v-for="(item,index) in cityList" :key="index" class="xzy-each">
						<view class="xzy-eachTitle" :id="'xzy-'+index">{{index}}</view>
						<view class="xzy-card">
							<view v-for="(ite,ind) in item" :key="ite[idValue]" class="card-item" @tap="selectIndex(ite)">
								<view class="xzy-name">{{ite[nameValue]}}</view>
							</view>
						</view>
					</view>
				</block>

			</view>
		</scroll-view>
	</view>
</template>

<script>
	export default {
		name: 'xzy-indexList',
		data() {
			return {
				inputKey: '', //搜索关键字
				searchTimeout: null, //搜索防抖
				searchList: [], //搜索内容
				scrollEachId: 'all', //跳转到对应列表子项的id
				toastIndex: '', //当前索引提示内容
				indexEachHH: 36, //索引项的高度，单位rpx
				afterConverHH: 0, //索引项的高度转换成PX值
				indexFirstTT: 0, //索引第一个子元素顶部位置，单位px
				indexLastBB: 0, //索引最后一个子元素底部位置，单位px
				isOk: true, //索引滑动节流
				isIndexGo: false, //在滑动索引时是否让列表跳转
				currentCeiling: null, //当前吸顶项和当前索引
				listInfo: [], //列表分类项位置信息
				scrollInfo: {}, //scroll的位置信息
				scrollTop: 0.01, //跳转至scroll某个位置
				isOkCurrent: false, //当列表不长时，吸顶就不显示
				top: 0
			}
		},
		props: {
			//右侧索引
			letters: {
				type: Array,
				default: () => []
			},
			//是否显示右侧索引
			isLetters: {
				type: Boolean,
				default: true
			},
			//是否显示索引提示
			isIndexToast: {
				type: Boolean,
				default: true
			},
			//id对应的值名
			idValue: {
				type: String,
				default: 'id'
			},
			//名字对应的值名
			nameValue: {
				type: String,
				default: 'name'
			},
			//当前城市
			currentCity: {
				type: Object,
				default: () => {}
			},
			//是否显示当前城市
			isCurrentCity: {
				type: Boolean,
				default: true
			},
			//热门城市
			hotCity: {
				type: Array,
				default: () => []
			},
			//是否显示热门城市
			isHotCity: {
				type: Boolean,
				default: true
			},
			//是否显示搜索
			isSearch: {
				type: Boolean,
				default: true
			},
			//城市列表
			cityList: {
				type: Object,
				default: () => {}
			},
			//是否显示头像
			isAvatar: {
				type: Boolean,
				default: false
			},
			//头像对应的值名
			avatarValue: {
				type: String,
				default: 'avatar'
			},
			//是否显示副标题
			isFu: {
				type: Boolean,
				default: false
			},
			//副标题对应的值名
			fuValue: {
				type: String,
				default: 'fu'
			},
			//是否吸顶
			isCeil: {
				type: Boolean,
				default: true
			},
			//是否显示当前索引背景色
			isIndexAc: {
				type: Boolean,
				default: true
			},
			//当前索引背景色
			indexAcColor: {
				type: String,
				default: '#6F69E9'
			},
			//是否显示回顶部图标
			isTop: {
				type: Boolean,
				default: false
			},
			type: {
				type: String,
				default: "list"
			},
			hotCityName: {
				type: String,
				default: "热门城市"
			}
		},
		mounted() {
			this.afterConverHH = uni.upx2px(this.indexEachHH); //将索引项的高度值转成px
			this.getLocation();
		},
		methods: {
			//回顶部
			goTop() {
				this.scrollTop = 0;
				//防止第二次点击不跳
				setTimeout(() => {
					this.scrollTop = 0.01;
				}, 200)
			},
			//搜索输入
			searchInput() {
				if (this.searchTimeout) {
					clearTimeout(this.searchTimeout)
				}
				if (!this.inputKey) {
					this.searchList = [];
					return
				}
				//查询匹配的数据
				this.searchTimeout = setTimeout(() => {
					let data = this.cityList;
					let result = [];
					let list = Object.values(data).flat();
					list.map(r => {
						if (r[this.nameValue].indexOf(this.inputKey) !== -1) {
							result.push(r)
						}
					})
					this.searchList = result;
					if (result.length === 0) {
						uni.$uv.toast("暂无搜索数据~");
					}
				}, 800)
			},
			//获取节点信息
			getLocation() {
				const that = this;
				//获取每项索引的位置信息
				uni.createSelectorQuery()
					.in(this)
					.selectAll('.xzy-lettersEach')
					.boundingClientRect(rect => {
						that.indexFirstTT = Math.round(rect[0]?.top);
						that.indexLastBB = Math.round(rect[rect.length - 1]?.bottom);
					})
					.exec();

				//获取scroll位置信息
				uni.createSelectorQuery()
					.in(this)
					.select('.xzy-scroll')
					.boundingClientRect(rect => {
						that.scrollInfo = rect;
					})
					.exec();

				//获取列表每个分类项位置信息
				uni.createSelectorQuery()
					.in(this)
					.selectAll('.xzy-eachTitle')
					.boundingClientRect(rect => {
						that.listInfo = rect;
					})
					.exec();
			},
			//监听滚动
			listenScroll(e) {
				let top = this.scrollInfo?.top || e.target.offsetTop; //scroll顶部的位置
				let scrollTop = e.detail.scrollTop; //scroll滚动了多少
				let allTop = top + scrollTop;
				if (this.currentCeiling !== null) {

					//大于最后一个
					if (allTop >= this.listInfo[this.listInfo.length - 1]?.top) {
						this.currentCeiling = this.listInfo.length - 1;
						return
					} else if (allTop > this.listInfo[this.currentCeiling]?.top && allTop > this.listInfo[this
							.currentCeiling + 1]?.top) {
						//当前位置远大于上一个的位置，通过遍历查询在哪
						//查询当前所在的位置
						let aa = this.listInfo.slice(this.currentCeiling + 1, this.listInfo.length); //截取后半段遍历
						let bb = true;
						aa.some((r, v) => {
							if (allTop < r?.top && bb) {
								this.currentCeiling += v;
								bb = false;
							}
						})
						return
					}

					if (allTop < 280) {
						this.isOkCurrent = false;
						this.currentCeiling = null
					}

					//当前位置小于之前
					if (allTop < this.listInfo[this.currentCeiling]?.top) {
						//小于第一个就隐藏
						if (allTop < this.listInfo[0].top) {
							this.currentCeiling = 0;
						} else {
							let aa = this.listInfo.slice(0, this.currentCeiling).reverse(); //截取前半段遍历并倒序
							let bb = true;
							aa.some((r, v) => {
								if (allTop >= r.top && bb) {
									if (this.currentCeiling === 0) {
										this.currentCeiling = this.currentCeiling - v - 1;
									} else {
										this.currentCeiling = this.currentCeiling - v;
									}

									bb = false;
								} else {}
							})
						}
					}
				} else {

					if (allTop > 260) {
						this.isOkCurrent = true;
					}

					//在第一个与第二个之间
					if (this.listInfo.length > 0 && allTop >= this.listInfo[0].top && allTop < this.listInfo[1].top) {
						this.currentCeiling = 0;
						//当列表够长时才让吸顶显示
						// if (!this.isOkCurrent) {
						// 	this.isOkCurrent = true;
						// }
					} else if (this.listInfo.length > 0 && allTop > this.listInfo[0].top && allTop > this.listInfo[1]
						.top) {
						let bb = true;
						this.listInfo.some((r, v) => {
							if (allTop < r.top && bb) {
								this.currentCeiling = v;
								bb = false;
							}
						})
						//当列表够长时才让吸顶显示
						// if (!this.isOkCurrent) {
						// 	this.isOkCurrent = true;
						// }
					} else {
						this.currentCeiling = null;
					}
				}
			},
			//选取
			selectIndex(e) {
				if (!e || e.target) return;
				this.$emit('cityClick', e);
			},
			//点击索引跳对应项
			handleLetterClick(e, index) {
				this.scrollEachId = 'xzy-' + e;
				this.currentCeiling = index;
			},
			//手指在索引滑动中
			handleTouchMove(e) {
				if (this.isOk) {
					//节流
					this.isOk = false;
					setTimeout(() => {
						//当前滑动到的位置
						if (e.touches[0]) {
							let nowY = Math.round(e.touches[0].pageY); //四舍五入
							//在索引区域内
							if (nowY >= this.indexFirstTT && nowY <= this.indexLastBB) {
								let aa = nowY - this.indexFirstTT;
								let bb = aa / this.afterConverHH;
								let cc = parseInt(bb);
								this.top = nowY
								if (bb > cc) {
									this.toastIndex = this.letters[cc]; //提示索引
									//当end方法比move方法先执行时
									if (this.isIndexGo) {
										this.isIndexGo = false;
										this.currentCeiling = cc;
										this.scrollEachId = 'xzy-' + this.letters[cc]; //跳到索引指定位置
										setTimeout(() => {
											this.toastIndex = ''; //关闭提示
										}, 700)
									}
								} else {
									this.toastIndex = this.letters[cc - 1]; //提示索引
									//当end方法比move方法先执行时
									if (this.isIndexGo) {
										this.isIndexGo = false;
										this.currentCeiling = cc - 1;
										this.scrollEachId = 'xzy-' + this.letters[cc - 1]; //跳到索引指定位置
										setTimeout(() => {
											this.toastIndex = ''; //关闭提示
										}, 700)
									}
								}
							} else {
								//超出范围就为空
								this.toastIndex = '';
							}
						}
						this.isOk = true;
					}, 100)
				}
			},
			//手指在索引滑动结束
			handleTouchEnd(e, index) {
				//有索引值才跳转
				if (this.toastIndex) {
					//isOk为true代表滑动真正结束，否则让isIndexGo来决定最后跳转
					//由于滑动方法处做了节流，当快速滑动时end会比move先执行
					if (this.isOk) {
						this.scrollEachId = 'xzy-' + this.toastIndex; //跳到索引指定位置
						this.currentCeiling = index;
						setTimeout(() => {
							this.toastIndex = '';
						}, 700)
					} else {
						this.isIndexGo = true; //让滑动处来执行跳转
					}
				}
			},

			replaceUrl(url) {
				if (uni.getStorageSync("__GLOBAL_STORE")) {
					if (url) {
						if (url.includes("http://") || url.includes("https://")) {

							return url
						} else {
							const tag_url = JSON.parse(uni.getStorageSync("__GLOBAL_STORE"))?.userInfo?.ossFilePreview
							return tag_url + url
						}
					}
				}
			}
		}
	}
</script>

<style lang="scss" scoped>
	.xzy-bigbox {
		// position: absolute;
		// top: 0;
		// left: 0;
		height: 100%;
		width: 100vw;
		background-color: #fff;

		/* 搜索 */
		.xzy-search {
			width: calc(100vw - 60rpx);
			margin: auto;
		}

		/*搜索结果*/
		.xzy-searchScroll {
			position: absolute;
			top: 90rpx;
			left: 0;
			width: 100%;
			height: calc(100% - 90rpx);
			background: #fff;
			padding: 0 30rpx;
			box-sizing: border-box;
		}

		/*右侧索引*/
		.xzy-letters {
			position: absolute;
			top: 0;
			right: 0;
			width: 60rpx;
			z-index: 6;
			display: flex;
			flex-direction: column;
			justify-content: center;
			align-items: center;

			.xzy-letterTop {
				width: 36rpx;
				height: 36rpx;
			}

			.xzy-lettersEach {
				width: 36rpx;
				height: 36rpx;
				display: flex;
				align-items: center;
				justify-content: center;
				color: #333;
				font-size: 24rpx;
			}

			.xzy-lettersEachAc {
				color: #fff;
				border-radius: 50%;
			}
		}

		/*当前索引提示内容*/
		.xzy-toastIndex {
			position: absolute;
			right: 60rpx;
			width: 100rpx;
			height: 60rpx;
			line-height: 60rpx;
			font-size: 35rpx;
			font-weight: 700;
			border-radius: 20rpx;
			z-index: 6;
			color: #333333;
		}


		/* 当前与热门 */
		.xzy-modu {
			width: 100%;
			padding: 20rpx 30rpx;
			box-sizing: border-box;

			.xzy-current {
				width: 100%;
				padding-bottom: 20rpx;
				margin-bottom: 50rpx;
			}

			.xzy-hotCity {
				width: 100%;
			}

			.xzy-moduTitle {
				width: 100%;
				font-size: 28rpx;
				color: #222222;
				font-weight: 600;
				margin-bottom: 20rpx;
			}

			.xzy-currentBox {
				width: 100%;
				display: flex;
				align-items: center;

				.xzy-currentLs {
					border-radius: 12rpx;
					background-color: #fff;
					border: 1rpx solid #ECECEC;
					width: 210rpx;
					height: 80rpx;
					display: flex;
					align-items: center;
					justify-content: center;
					box-sizing: border-box;

					.xzy-currentImg {
						width: 42rpx;
						height: 42rpx;
						margin-right: 10rpx;
					}

					.xzy-currentCity {
						color: #333;
						font-size: 28rpx;
					}
				}
			}

			.xzy-hotCityBox {
				width: 100%;
				display: flex;
				flex-wrap: wrap;
				justify-content: flex-start;

				.xzy-hotEachCity {

					background: #f5f5f5;
					border-radius: 16rpx;
					padding: 22rpx 24rpx;
					color: #222222;
					font-size: 28rpx;
					margin-bottom: 24rpx;
					display: flex;
					justify-content: center;
					margin-right: 24rpx;
				}
			}
		}

		/* 数据列表 */
		.xzy-scroll {
			position: absolute;
			width: 100%;
			left: 0;
			background-color: #fff;
			font-size: 28rpx;

			.xzy-each {
				width: 100%;

				.xzy-eachTitle {
					font-size: 28rpx;
					color: #999;
					background-color: #dedede;
					text-align: left;
					padding: 10rpx 30rpx;
					box-sizing: border-box;
					font-weight: 700;
				}

				.xzy-second {
					width: 100%;
					padding: 0 30rpx;
					box-sizing: border-box;
				}

				.xzy-card {
					display: flex;
					align-items: center;
					flex-wrap: wrap;

					.card-item {
						padding: 10rpx 30rpx;
						margin: 20rpx;
						background: #F4F3F9;
						border-radius: 10rpx;
						color: #333333;
					}
				}
			}
		}

		/*吸顶*/
		.ceiling {
			position: absolute;
			left: 0;
			width: 100%;
			z-index: 1;
			font-size: 32rpx;
			color: #333;
			background-color: #dedede;
			padding: 10rpx 30rpx;
			box-sizing: border-box;
			font-weight: 600;
		}

		/*搜索结果与列表的每一项*/
		.xzy-secondEach {
			width: 100%;
			display: flex;
			align-items: center;
			padding: 20rpx 0;
			border-bottom: 2rpx solid #f4f4f4;

			.xzy-avatar {
				width: 90rpx;
				height: 90rpx;
				margin-right: 20rpx;

				.xzy-avatarImg {
					width: 100%;
					height: 100%;
					border-radius: 8rpx;
				}
			}

			.xzy-text {
				flex: 1;
				display: flex;
				flex-direction: column;
				justify-content: center;

				.xzy-name {
					font-size: 30rpx;
					color: #333;
				}

				.xzy-fu {
					font-size: 24rpx;
					color: #999;
				}
			}
		}

		.xzy-secondEach:last-child {
			border-bottom: none;
		}
	}
</style>